
    use: 'ie.ondevice.objectkit.utility.statemachine.State';
    use: 'ie.ondevice.objectkit.utility.statemachine.StateMachine';

    TestCase
    (
        'ie.ondevice.objectkit.utility.statemachine.StateMachineTestCase'
        
    ,   new function ()
        {
            
            var StateMachineError= 
                {
                    UNSET_STATE: 'unsetState' 
                };
            
            MockStateMachine.inherit(StateMachine).implement
            (
                {
                    /**
                     * @public
                     * Flag variable recording whether state changed
                     * @type {Boolean}
                     */
                    didChangeState: null
                    
                    /**
                     * @public
                     * Flag variable recording state change permissions
                     * @type {Boolean}
                     */
                ,   didAllowChangeState: null
                    
                    /** @override */
                ,   setState: function (newState) 
                    {
                        this.parent.setState.call(this, newState);
                        this.didChangeState= this.state === newState; 
                    }
                    
                    /** @override */
                ,   canEnterState: function (value) 
                    {
                        return this.didAllowChangeState= !!this.parent.canEnterState.call(this, value);
                    }
                    
                    /**
                     * @public
                     * @return {State} the machines current state
                     * @throws {Error} if state is unset
                     */
                ,   getState: function () 
                    {
                        if (null == this.state)
                            throw new Error(StateMachineError.UNSET_STATE);
                            
                        return this.state;
                    }  
                    
                    /**
                     * Reset the mock state machine.
                     * @public
                     * @return {void}
                     */
                ,   reset: function () 
                    {
                        StateMachine.call(this);
                        this.didAllowChangeState= false;
                        this.didChangeState= false;
                    }      
                }
            );
            
            /**
             * An inner class for testing state machine
             * @constructor
             */
            function MockStateMachine () 
            {
                this.reset();
            };
            
            
            MockState.inherit(State).implement
            (
                {
                    /**
                     * @public
                     * A flag variable tracking whether this state is currently
                     * the state machine state or not.
                     * @type {Boolean}
                     */
                    isMachineState: null
                    
                    /**
                     * @type {Boolean}
                     */
                ,   throwErrorOnEnter: null
                    
                    /**
                     * @type {Boolean}
                     */
                ,   throwErrorOnExit: null

                    /** @override */
                ,   enter: function () 
                    {
                        this.isMachineState= true;
                        if (true === this.throwErrorOnEnter)
                            throw new Error('Cannot enter state');
                    }
                    
                    /** @override */
                ,   exit: function () 
                    {
                        this.isMachineState= false;
                        if (true === this.throwErrorOnExit)
                            throw new Error('Cannot exit state');
                    }
                }
            );
            
            /**
             * @override
             * @constructor
             */
            function MockState (machine) 
            {
                State.call(this, machine);
                this.isMachineState= false;
                this.throwErrorOnEnter= false;
                this.throwErrorOnExit= false;
            };
            
            
            
            
            
            this.constructor.implement
            (
                {
                    setUp: function () 
                    {
                        
                    }
                
                ,   tearDown: function () 
                    {
                        
                    }    
                    
                ,   testDefaultState: function () 
                    {
                        var machine= new MockStateMachine
                        ,   state
                        ,   error
                        
                        try 
                        {
                            state= machine.getState();
                        }
                        catch (thrown) 
                        {
                            error= thrown;
                        }
                        
                        assertUndefined('The state accessor did not throw an error', error);
                        assertInstanceOf('The default state was retrieved', State, state);
                        assertSame('The default state constructor is State', State, state.constructor);
                    }
                    
                ,   testSetStateAndStateTransition: function () 
                    {
                        var machine= new MockStateMachine
                        ,   oldState= machine.getState()
                        ,   newState= new MockState(machine)
                        ,   error
                        ;
                        
                        
                        assertFalse('The new state has not entered', newState.isMachineState);
                        assertFalse('The state machine has not yet changed state', machine.didChangeState);
                        assertFalse('The state machine has not yet allowed change state', machine.didAllowChangeState);
                        
                        machine.setState(newState);
                        
                        assertTrue ('The state entered', newState.isMachineState);
                        assertSame ('The state is machine.state', newState, machine.getState());
                        assertTrue ('The machine allowed transition', machine.didAllowChangeState);
                        assertTrue ('The machine registed transition', machine.didChangeState);
                        
                        machine.setState(oldState);
                        
                        assertFalse ('The state exited', newState.isMachineState);
                        assertSame ('The state is machine.state', oldState, machine.getState());
                        assertTrue ('The machine allowed transition', machine.didAllowChangeState);
                        assertTrue ('The machine registed transition', machine.didChangeState);
                        
                        try 
                        {
                            machine.setState(oldState);
                        }
                        catch (thrown) 
                        {
                            error= thrown;
                        }
                        
                        assertFalse('The machine should not have allowed the state change', machine.didAllowChangeState);
                        assertUndefined('No error should have been thrown', error);
                        
                        machine.reset();
                        error= void(0);
                        
                        try 
                        {
                            machine.setState(4);
                        }
                        catch (thrown) 
                        {
                            error= thrown;
                        }
                        
                        assertFalse('The machine should not have allowed the state change', machine.didAllowChangeState);
                        assertInstanceOf('A type error should have been thrown', TypeError, error);
                        error= null
                        
                        machine= new MockStateMachine;
                        
                        newState.throwErrorOnEnter= true;
                        
                        try 
                        {
                            machine.setState(newState);
                        }
                        catch (thrown) 
                        {
                            console.log('An error was thrown: ' + thrown);
							error= thrown;
                        }

                        assertTrue('The machine did allow the transition', machine.didAllowChangeState);
                        assertFalse('The machine did not enter the new state', machine.didChangeState);
                        assertNotNull('An error was thrown', error);
                        assertInstanceOf('A state transition exception was thrown entering state', StateTransitionException, error);
                    }
                }
            )
        }
    );
